﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YJKArch.AreaSet;
using YJKArch.AreaStatistical.DataManager;
using YJKArch.AreaStatistical.SearchLoop;
using YJKRGeometry;

namespace YJKArch.AreaShowHide
{
	internal class AreaShowHideManager
	{
		public AreaShowHideManager(ExternalCommandData commandData)
		{
			this.m_uiDoc = commandData.Application.ActiveUIDocument;
			this.m_doc = this.m_uiDoc.Document;
			this.m_view = this.m_doc.ActiveView;
			this.CreateFilledRegionType();
		}

		private void CreateFilledRegionType()
		{
			FilledRegionType filledRegionType = null;
			foreach (Element element in new FilteredElementCollector(this.m_doc).OfClass(typeof(FilledRegionType)).ToList<Element>())
			{
				FilledRegionType filledRegionType2 = element as FilledRegionType;
				if (filledRegionType2 != null && filledRegionType2.Name.Contains("实体填充"))
				{
					filledRegionType = filledRegionType2;
					break;
				}
			}
			Transaction transaction = new Transaction(this.m_doc, "Create FilledRegionType");
			try
			{
				transaction.Start();
				this.m_frTypeBuild = (filledRegionType.Duplicate("实体填充-建筑面积") as FilledRegionType);
				this.m_frTypeFire = (filledRegionType.Duplicate("实体填充-防火分区") as FilledRegionType);
				this.m_frTypeInner = (filledRegionType.Duplicate("实体填充-套内面积") as FilledRegionType);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		public Result Creator()
		{
			AreaShowHideForm areaShowHideForm = new AreaShowHideForm(this.IfDrawnAreaRegion());
			areaShowHideForm.Show(CmdAreaShowHide._hWndRevit);
			int wMsg = 7;
			AreaShowHideManager.SendMessage(CmdAreaShowHide._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			try
			{
				for (;;)
				{
					try
					{
						this.m_uiDoc.Selection.PickElementsByRectangle("");
						continue;
					}
					catch (Exception)
					{
					}
					break;
				}
			}
			catch (Exception)
			{
				areaShowHideForm.Close();
				return Autodesk.Revit.UI.Result.Failed;
			}
			areaShowHideForm.Close();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private bool IfDrawnAreaRegion()
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			filteredElementCollector.OfClass(typeof(FilledRegion));
			foreach (Element element in filteredElementCollector)
			{
				FilledRegion filledRegion = element as FilledRegion;
				if (filledRegion != null)
				{
					Parameter parameter = filledRegion.GetParameter(BuiltInParameter.ELEM_TYPE_PARAM);
					if (parameter != null)
					{
						FilledRegionType filledRegionType = this.m_doc.GetElement(parameter.AsElementId()) as FilledRegionType;
						AreaFilledRegion areaFilledRegion = new AreaFilledRegion();
						if (filledRegionType.Name.Contains("建筑面积"))
						{
							areaFilledRegion.areaRegionCategory = AreaCategory.eAreaBuild;
						}
						else if (filledRegionType.Name.Contains("套内面积"))
						{
							areaFilledRegion.areaRegionCategory = AreaCategory.eAreaInner;
						}
						else if (filledRegionType.Name.Contains("防火分区"))
						{
							areaFilledRegion.areaRegionCategory = AreaCategory.eAreaFire;
						}
						areaFilledRegion.areaRegionTypeId = filledRegionType.Id;
						this.m_dicAreaRegionAndType.Add(filledRegion.Id, areaFilledRegion);
					}
				}
			}
			return this.m_dicAreaRegionAndType.Count > 0;
		}

		public List<AreaCategory> ShowArea(List<AreaCategory> lstAreaCategory)
		{
			List<AreaCategory> list = new List<AreaCategory>();
			foreach (AreaCategory areaCategory in lstAreaCategory)
			{
				List<ElementId> specialArea = this.GetSpecialArea(areaCategory);
				if (specialArea.Count <= 0)
				{
					list.Add(areaCategory);
				}
				else
				{
					this.FilterExistAreaRegion(specialArea);
					this.DrawAreaRegion(specialArea, areaCategory);
				}
			}
			return list;
		}

		private void FilterExistAreaRegion(List<ElementId> lstAreaId)
		{
			foreach (KeyValuePair<ElementId, AreaFilledRegion> keyValuePair in this.m_dicAreaRegionAndType)
			{
				FilledRegion filledRegion = this.m_doc.GetElement(keyValuePair.Key) as FilledRegion;
				if (filledRegion != null)
				{
					string text = this.ReadExtendAreaId(filledRegion);
					if (!(text == ""))
					{
						Area area = this.m_doc.GetElement(text) as Area;
						if (area != null && lstAreaId.Contains(area.Id))
						{
							lstAreaId.Remove(area.Id);
						}
					}
				}
			}
		}

		private void DrawAreaRegion(List<ElementId> lstAreaId, AreaCategory eAreaCategory)
		{
			if (lstAreaId.Count <= 0)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_doc, "Create Area Group");
			try
			{
				transaction.Start();
				this.m_doc.Application.FailuresProcessing += this.OnFailuresProcessing;
				ElementSet elementSet = new ElementSet();
				foreach (ElementId elementId in lstAreaId)
				{
					Element element = this.m_doc.GetElement(elementId);
					if (element != null)
					{
						CurveLoop areaOutLines = this.GetAreaOutLines(element, eAreaCategory);
						if (areaOutLines.Count<Curve>() > 0)
						{
							List<CurveLoop> list = new List<CurveLoop>();
							list.Add(areaOutLines);
							SubTransaction subTransaction = new SubTransaction(this.m_doc);
							try
							{
								subTransaction.Start();
								FilledRegionType filledRegionType = null;
								switch (eAreaCategory)
								{
								case AreaCategory.eAreaBuild:
									filledRegionType = (this.m_frTypeBuild.Duplicate("建筑面积" + elementId.ToString()) as FilledRegionType);
									break;
								case AreaCategory.eAreaInner:
									filledRegionType = (this.m_frTypeBuild.Duplicate("套内面积" + elementId.ToString()) as FilledRegionType);
									break;
								case AreaCategory.eAreaFire:
									filledRegionType = (this.m_frTypeBuild.Duplicate("防火分区" + elementId.ToString()) as FilledRegionType);
									break;
								}
								filledRegionType.Color = this.CreateRandomColor();
                                filledRegionType.Background = (FilledRegionBackground)1;
								FilledRegion filledRegion = FilledRegion.Create(this.m_doc, filledRegionType.Id, this.m_doc.ActiveView.Id, list);
								this.WriteExtendAreaId(filledRegion, element.UniqueId);
								AreaFilledRegion areaFilledRegion = new AreaFilledRegion();
								areaFilledRegion.areaRegionCategory = eAreaCategory;
								areaFilledRegion.areaRegionTypeId = filledRegionType.Id;
								this.m_dicAreaRegionAndType.Add(filledRegion.Id, areaFilledRegion);
								elementSet.Insert(filledRegion);
								subTransaction.Commit();
							}
							catch (Exception)
							{
								subTransaction.RollBack();
							}
						}
					}
				}
				if (elementSet.Size <= 0)
				{
					transaction.RollBack();
				}
				else
				{
					this.m_doc.CreatYJKGroup(elementSet);
					transaction.Commit();
				}
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private CurveLoop GetAreaOutLines(Element elemArea, AreaCategory eAreaCategory)
		{
			CurveLoop curveLoop = new CurveLoop();
			List<ElementId> list;
			if (eAreaCategory == AreaCategory.eAreaFire || eAreaCategory == AreaCategory.eAreaInner)
			{
				list = Common.ReadAreaData(elemArea);
			}
			else
			{
				list = AreaLoopSearcher.ReadAreaData(elemArea);
			}
			if (list == null)
			{
				return curveLoop;
			}
			foreach (ElementId elementId in list)
			{
				ModelCurve modelCurve = this.m_doc.GetElement(elementId) as ModelCurve;
				if (modelCurve != null)
				{
					curveLoop.Append(modelCurve.GeometryCurve);
				}
			}
			return curveLoop;
		}

		private void OnFailuresProcessing(object sender, FailuresProcessingEventArgs e)
		{
			e.GetFailuresAccessor().DeleteAllWarnings();
		}

		private void WriteExtendAreaId(FilledRegion region, string strAreaUniqueId)
		{
			Guid guid = new Guid("4F8161E6-12F5-4FA4-B5F6-B1913E18A434");
			Schema schema = Schema.Lookup(guid);
			if (schema == null)
			{
				SchemaBuilder schemaBuilder = new SchemaBuilder(guid);
				schemaBuilder.SetSchemaName("AreaIdExtendedData");
				schemaBuilder.AddSimpleField("AreaId", typeof(string));
				schema = schemaBuilder.Finish();
			}
			Entity entity = new Entity(schema);
			Field field = schema.GetField("AreaId");
			entity.Set<string>(field, strAreaUniqueId);
			region.SetEntity(entity);
		}

		private string ReadExtendAreaId(FilledRegion region)
		{
			if (region == null)
			{
				return "";
			}
			Schema schema = Schema.Lookup(new Guid("4F8161E6-12F5-4FA4-B5F6-B1913E18A434"));
			if (schema == null)
			{
				return "";
			}
			Entity entity = region.GetEntity(schema);
			if (entity == null)
			{
				return "";
			}
			if (entity.Schema == null)
			{
				return "";
			}
			Field field = schema.GetField("AreaId");
			return entity.Get<string>(field);
		}

        private Autodesk.Revit.DB.Color CreateRandomColor()
		{
			long ticks = DateTime.Now.Ticks;
			Random random = new Random((int)(ticks & (long)(-1)) | (int)(ticks >> 32));
			int num = random.Next(100, 254);
			int num2 = random.Next(100, 254);
			int num3 = random.Next(100, 254);
			num3 = ((num + num2 > 400) ? (num + num2 - 400) : num3);
			num3 = ((num3 > 255) ? 255 : num3);
            return new Autodesk.Revit.DB.Color((byte)num, (byte)num2, (byte)num3);
		}

		public bool HideArea(List<AreaCategory> lstAreaCategory)
		{
			List<ElementId> list = new List<ElementId>();
			List<ElementId> list2 = new List<ElementId>();
			foreach (AreaCategory areaCategory in lstAreaCategory)
			{
				foreach (ElementId elementId in this.m_dicAreaRegionAndType.Keys.ToList<ElementId>())
				{
					if (this.m_dicAreaRegionAndType[elementId].areaRegionCategory == areaCategory)
					{
						list.Add(elementId);
						list2.Add(this.m_dicAreaRegionAndType[elementId].areaRegionTypeId);
						this.m_dicAreaRegionAndType.Remove(elementId);
					}
				}
			}
			this.ClearAreaRegionAndType(list, list2);
			return this.m_dicAreaRegionAndType.Count <= 0;
		}

		private void ClearAreaRegionAndType(List<ElementId> lstDrewRegionId, List<ElementId> lstFilledRegionTypeId)
		{
			if (lstDrewRegionId.Count <= 0)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_doc, "Delete Area Region");
			try
			{
				transaction.Start();
				this.m_doc.Delete(lstDrewRegionId);
				this.m_doc.Delete(lstFilledRegionTypeId);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			lstDrewRegionId.Clear();
		}

		public void ClearOrigionFilledRegionType()
		{
			Transaction transaction = new Transaction(this.m_doc, "Delete FilledRegionType");
			try
			{
				transaction.Start();
				this.m_doc.Delete(this.m_frTypeBuild.Id);
				this.m_doc.Delete(this.m_frTypeInner.Id);
				this.m_doc.Delete(this.m_frTypeFire.Id);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private List<ElementId> GetSpecialArea(AreaCategory eAreaCategory)
		{
			List<ElementId> result = new List<ElementId>();
			this.GetCurrentDocSpecialArea(eAreaCategory, ref result);
			this.GetLinkDocSpecialArea(eAreaCategory, ref result);
			return result;
		}

		private void GetCurrentDocSpecialArea(AreaCategory eAreaCategory, ref List<ElementId> lstAreaId)
		{
			List<ViewPlan> specialViewPlan = this.GetSpecialViewPlan(eAreaCategory, this.m_doc);
			if (specialViewPlan.Count <= 0)
			{
				return;
			}
			this.GetSpecialArea(this.m_doc, specialViewPlan, eAreaCategory, ref lstAreaId);
		}

		private void GetLinkDocSpecialArea(AreaCategory eAreaCategory, ref List<ElementId> lstAreaId)
		{
			IEnumerable<Document> linkDocuments = this.m_doc.GetLinkDocuments();
			if (linkDocuments == null || linkDocuments.Count<Document>() <= 0)
			{
				return;
			}
			foreach (Autodesk.Revit.DB.Document document in linkDocuments)
			{
				if (document != null)
				{
					List<ViewPlan> specialViewPlan = this.GetSpecialViewPlan(eAreaCategory, document);
					if (specialViewPlan.Count > 0)
					{
						this.GetSpecialArea(document, specialViewPlan, eAreaCategory, ref lstAreaId);
					}
				}
			}
		}

		private void GetSpecialArea(Autodesk.Revit.DB.Document doc, List<ViewPlan> lstViewPlan, AreaCategory eAreaCategory, ref List<ElementId> lstAreaId)
		{
			foreach (Autodesk.Revit.DB.ViewPlan viewPlan in lstViewPlan)
			{
				foreach (Element element in new FilteredElementCollector(doc, viewPlan.Id).OfClass(typeof(SpatialElement)))
				{
					Area area = element as Area;
					if (area != null)
					{
						switch (eAreaCategory)
						{
						case AreaCategory.eAreaBuild:
						{
							AreaType areaType = AreaType.AT_None;
							AreaInfoManager.HaxExtensibleStorageInArea(area, ref areaType);
							if (AreaType.AT_Fill == areaType)
							{
								lstAreaId.Add(area.Id);
							}
							break;
						}
						case AreaCategory.eAreaInner:
						{
							AreaType areaType2 = AreaType.AT_None;
							AreaInfoManager.HaxExtensibleStorageInArea(area, ref areaType2);
							if (AreaType.AT_Suite == areaType2)
							{
								lstAreaId.Add(area.Id);
							}
							break;
						}
						case AreaCategory.eAreaFire:
							if (AreaInfoManager.AreaIsFireArea(area))
							{
								lstAreaId.Add(area.Id);
							}
							break;
						}
					}
				}
			}
		}

		private List<ViewPlan> GetSpecialViewPlan(AreaCategory eAreaCategory, Autodesk.Revit.DB.Document doc)
		{
			List<ViewPlan> list = new List<ViewPlan>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc).OfClass(typeof(ViewPlan));
			if (eAreaCategory == AreaCategory.eAreaBuild)
			{
				IEnumerator<Element> enumerator = filteredElementCollector.GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						Element element = enumerator.Current;
						ViewPlan viewPlan = element as Autodesk.Revit.DB.ViewPlan;
						if (viewPlan != null && (int)viewPlan.ViewType == 116 && viewPlan.AreaScheme.Name.Contains("建筑面积") && Geometry.IsEqual(viewPlan.GenLevel.Elevation, this.m_view.GenLevel.Elevation))
						{
							list.Add(viewPlan);
						}
					}
					return list;
				}
			}
			if (AreaCategory.eAreaFire == eAreaCategory)
			{
				IEnumerator<Element> enumerator = filteredElementCollector.GetEnumerator();
				{
					while (enumerator.MoveNext())
					{
						Element element2 = enumerator.Current;
						ViewPlan viewPlan2 = element2 as Autodesk.Revit.DB.ViewPlan;
						if (viewPlan2 != null && (int)viewPlan2.ViewType == 116 && viewPlan2.AreaScheme.Name.Contains("防火分区"))
						{
							list.Add(viewPlan2);
						}
					}
					return list;
				}
			}
			if (AreaCategory.eAreaInner == eAreaCategory)
			{
				foreach (Element element3 in filteredElementCollector)
				{
					ViewPlan viewPlan3 = element3 as Autodesk.Revit.DB.ViewPlan;
					if (viewPlan3 != null && (int)viewPlan3.ViewType == 116 && viewPlan3.AreaScheme.Name.Contains("套内面积"))
					{
						list.Add(viewPlan3);
					}
				}
			}
			return list;
		}

		public const string AreaBuildName = "建筑面积";

		public const string AreaFireName = "防火分区";

		public const string AreaInnerName = "套内面积";

		private UIDocument m_uiDoc;

		private Autodesk.Revit.DB.Document m_doc;

		private Autodesk.Revit.DB.View m_view;

		private Dictionary<ElementId, AreaFilledRegion> m_dicAreaRegionAndType = new Dictionary<ElementId, AreaFilledRegion>();

		private FilledRegionType m_frTypeBuild;

		private FilledRegionType m_frTypeInner;

		private FilledRegionType m_frTypeFire;

		private const string AREA_GUID = "4F8161E6-12F5-4FA4-B5F6-B1913E18A434";

		private const string AREA_SCHEMANAME = "AreaIdExtendedData";

		private const string AREA_AREAID = "AreaId";
	}
}
